import { IAdapter, IOptions } from './types'
interface IAbortControllerBucket {
  url: string
  options: IOptions
  controller: AbortController
}
/**
 * 请求控制器列表
 * 使用场景：页面销毁时，取消未完成的所有请求
 */
export const abortCtrBucket = new Set<IAbortControllerBucket>()
/**Fetch 请求适配器 */
export const fetchAdapter: IAdapter<Response> = (url: string, options: IOptions) => {
  const controller = new AbortController()
  const acb: IAbortControllerBucket = { url, options, controller }
  abortCtrBucket.add(acb)
  return new Promise((resolve, reject) => {
    const { baseURL, method, headers, data, timeout } = options
    let timer: any = 0
    fetch(baseURL + url, { method, headers, body: data, signal: controller.signal })
      .then((res) => (res.ok ? resolve(res) : reject(res)))
      .catch((err) => {
        if (err && err.name === 'TypeError' && /fetch/i.test(err.message)) {
          // 忽略网络错误或者页面刷新浏览器自动取消导致的错误
          console.log(err, 'ignore error [adapters.js]')
        } else {
          reject(err)
        }
      })
      .finally(() => {
        if (timer) {
          clearTimeout(timer)
        }
        abortCtrBucket.delete(acb)
      })

    if (timeout && timeout > 0) {
      timer = setTimeout(() => {
        if (!controller.signal.aborted) {
          controller.abort()
          reject({ status: 408, message: '请求超时', url, options })
        }
      }, timeout)
    }
  })
}
